package de.zainodis.triplog.data;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;

import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;

import java.util.ArrayList;
import java.util.List;

import de.zainodis.triplog.data.persistence.ITripDao;
import de.zainodis.triplog.data.persistence.IWeatherDao;
import de.zainodis.triplog.data.share.TriplogContract;
import de.zainodis.triplog.util.Utilities;

/*
 * Created by fzarrai on 8/18/2014.
 * Represents the forecast for a single day.
 */
@DatabaseTable(tableName = IWeatherDao.TABLE_NAME, daoClass = IWeatherDao.WeatherDao.class)
public class WeatherEntry implements Parcelable, ICrudOperations {
    private static final String TAG = "Weather";

    @DatabaseField(generatedId = true, columnName = IWeatherDao.COLUMN_ID)
    private long id;
    @DatabaseField(columnName = IWeatherDao.COLUMN_FK_LOCATION_ID)
    private long fkLocationEntry;
    @DatabaseField(columnName = IWeatherDao.COLUMN_WEATHER_ICON_ID)
    private int iconId;
    /**
     * Date in the format WeatherContract#DATE_FORMAT
     */
    @DatabaseField(columnName = IWeatherDao.COLUMN_DATETEXT, uniqueCombo = true)
    private String date;
    @DatabaseField(columnName = IWeatherDao.COLUMN_MAX_TEMP)
    private int max;
    @DatabaseField(columnName = IWeatherDao.COLUMN_MIN_TEMP)
    private int min;
    @DatabaseField(columnName = IWeatherDao.COLUMN_DESCRIPTION)
    private String description;
    @DatabaseField(columnName = IWeatherDao.COLUMN_HUMIDITY)
    private String humidity;
    @DatabaseField(columnName = IWeatherDao.COLUMN_WIND_SPEED)
    private float wind;
    @DatabaseField(columnName = IWeatherDao.COLUMN_DEGREES)
    private float windDirection;


    public WeatherEntry() {
    }


    public WeatherEntry(ContentValues values) {
        id = Utilities.getAsLong(values, IWeatherDao.COLUMN_ID);
        fkLocationEntry = Utilities.getAsLong(values, IWeatherDao.COLUMN_FK_LOCATION_ID);
        iconId = Utilities.getAsInteger(values, IWeatherDao.COLUMN_WEATHER_ICON_ID);

        date = Utilities.getAsString(values, IWeatherDao.COLUMN_DATETEXT);
        min = Utilities.getAsInteger(values, IWeatherDao.COLUMN_MIN_TEMP);
        max = Utilities.getAsInteger(values, IWeatherDao.COLUMN_MAX_TEMP);

        description = Utilities.getAsString(values, IWeatherDao.COLUMN_DESCRIPTION);
        humidity = Utilities.getAsString(values, IWeatherDao.COLUMN_HUMIDITY);
        wind = Utilities.getAsFloat(values, IWeatherDao.COLUMN_WIND_SPEED);
        windDirection = Utilities.getAsFloat(values, IWeatherDao.COLUMN_DEGREES);
    }

    /**
     * @return ContentValues for this WeatherEntry.
     */
    public ContentValues getContentValues() {
        ContentValues values = new ContentValues();
        values.put(IWeatherDao.COLUMN_ID, id);
        values.put(IWeatherDao.COLUMN_LOC_KEY, fkLocationEntry);
        values.put(IWeatherDao.COLUMN_DATETEXT, date);
        values.put(IWeatherDao.COLUMN_HUMIDITY, humidity);
        values.put(IWeatherDao.COLUMN_WIND_SPEED, wind);
        values.put(IWeatherDao.COLUMN_DEGREES, windDirection);
        values.put(IWeatherDao.COLUMN_MAX_TEMP, max);
        values.put(IWeatherDao.COLUMN_MIN_TEMP, min);
        values.put(IWeatherDao.COLUMN_DESCRIPTION, description);
        values.put(IWeatherDao.COLUMN_WEATHER_ICON_ID, iconId);

        return values;
    }

    public static final Parcelable.Creator<WeatherEntry> CREATOR
            = new Parcelable.Creator<WeatherEntry>() {
        public WeatherEntry createFromParcel(Parcel in) {
            return new WeatherEntry(in);
        }

        public WeatherEntry[] newArray(int size) {
            return new WeatherEntry[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeLong(id);
        out.writeLong(fkLocationEntry);
        out.writeInt(iconId);
        out.writeString(date);
        out.writeInt(max);
        out.writeInt(min);
        out.writeString(description);
        out.writeString(humidity);
        out.writeFloat(wind);
        out.writeFloat(windDirection);
    }

    private WeatherEntry(Parcel in) {
        id = in.readLong();
        fkLocationEntry = in.readLong();
        iconId = in.readInt();
        date = in.readString();
        max = in.readInt();
        min = in.readInt();
        description = in.readString();
        humidity = in.readString();
        wind = in.readFloat();
        windDirection = in.readFloat();
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    /**
     * @return true if the weather entry has an id set; false otherwise.
     */
    public boolean hasId() {
        return id > 0;
    }

    public int getIconId() {
        return iconId;
    }

    public void setIconId(int iconId) {
        this.iconId = iconId;
    }

    public float getWindDirection() {
        return windDirection;
    }

    public void setWindDirection(float windDegrees) {
        this.windDirection = windDegrees;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    /**
     * @return max temperature in celsius.
     */
    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        this.max = max;
    }

    /**
     * @return min temperature in celsius.
     */
    public int getMin() {
        return min;
    }

    public void setMin(int min) {
        this.min = min;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getHumidity() {
        return humidity;
    }

    public void setHumidity(String humidity) {
        this.humidity = humidity;
    }

    /**
     * @return wind in km/h
     */
    public float getWind() {
        return wind;
    }

    public void setWind(float wind) {
        this.wind = wind;
    }

    public long getFkLocationEntry() {
        return fkLocationEntry;
    }

    public void setFkLocationEntry(long fkLocationEntry) {
        this.fkLocationEntry = fkLocationEntry;
    }

    @Override
    public int delete(Context context) {
        int count = 0;
        if (id > 0) {
            //Delete the weather from the database
            count = context.getContentResolver().delete(TriplogContract.CONTENT_URI_WEATHER, IWeatherDao.COLUMN_ID + " = ?",
                    new String[]{String.valueOf(id)});
        }
        return count;
    }

    @Override
    public long createOrUpdate(Context context) {
        if (context == null) {
            Log.e(TAG, "Provided context is null.");
            return -1;
        }
        //Weather can be updated, so we need to first get the entry before we can insert or update
        Cursor cursor = context.getContentResolver().query(
                TriplogContract.CONTENT_URI_WEATHER, new String[]{IWeatherDao.COLUMN_ID}, IWeatherDao.COLUMN_DATETEXT + " = ?",
                new String[]{getDate()},
                null);
        if (cursor.moveToFirst()) {
            //Already exists, hence update
            id = cursor.getLong(cursor.getColumnIndex(ITripDao.COLUMN_ID));
            context.getContentResolver().update(TriplogContract.CONTENT_URI_WEATHER, getContentValues(), IWeatherDao.COLUMN_ID + " = ?", new String[]{String.valueOf(getId())});
        } else {
            //Does not exist yet, hence insert
            Uri uri = context.getContentResolver().insert(TriplogContract.CONTENT_URI_WEATHER, getContentValues());
            //Return id of the inserted trip instance
            id = ContentUris.parseId(uri);
        }
        return id;
    }

    public static WeatherEntry getByDate(Context context, String date) {
        if (date == null) {
            return null;
        }
        Cursor cursor = context.getContentResolver().query(
                TriplogContract.CONTENT_URI_WEATHER, null, IWeatherDao.COLUMN_DATETEXT + " = ?",
                new String[]{date},
                null);

        if (cursor.moveToNext()) {
            WeatherEntry entry = new WeatherEntry();
            entry.setDate(cursor.getString(cursor.getColumnIndex(IWeatherDao.COLUMN_DATETEXT)));
            entry.setId(cursor.getLong(cursor.getColumnIndex(IWeatherDao.COLUMN_ID)));
            entry.setFkLocationEntry(cursor.getLong(cursor.getColumnIndex(IWeatherDao.COLUMN_FK_LOCATION_ID)));
            entry.setDescription(cursor.getString(cursor.getColumnIndex(IWeatherDao.COLUMN_DESCRIPTION)));
            entry.setMax(cursor.getInt(cursor.getColumnIndex(IWeatherDao.COLUMN_MAX_TEMP)));
            entry.setMin(cursor.getInt(cursor.getColumnIndex(IWeatherDao.COLUMN_MIN_TEMP)));
            entry.setIconId(cursor.getInt(cursor.getColumnIndex(IWeatherDao.COLUMN_WEATHER_ICON_ID)));
            entry.setHumidity(cursor.getString(cursor.getColumnIndex(IWeatherDao.COLUMN_HUMIDITY)));
            entry.setWind(cursor.getFloat(cursor.getColumnIndex(IWeatherDao.COLUMN_WIND_SPEED)));
            entry.setWindDirection(cursor.getFloat(cursor.getColumnIndex(IWeatherDao.COLUMN_DEGREES)));
            return entry;
        }
        return null;
    }

    /**
     * @param id location id.
     * @return the weather entries linked to the given location id; an empty list if there are none.
     */
    public static List<WeatherEntry> getByLocationId(Context context, long id) {
        Cursor cursor = context.getContentResolver().query(
                TriplogContract.CONTENT_URI_WEATHER, null, IWeatherDao.COLUMN_FK_LOCATION_ID + " = ?",
                new String[]{String.valueOf(id)},
                null);
        List<WeatherEntry> result = new ArrayList<WeatherEntry>();

        while (cursor.moveToNext()) {
            WeatherEntry entry = new WeatherEntry();
            entry.setDate(cursor.getString(cursor.getColumnIndex(IWeatherDao.COLUMN_DATETEXT)));
            entry.setId(cursor.getLong(cursor.getColumnIndex(IWeatherDao.COLUMN_ID)));
            entry.setFkLocationEntry(id);
            entry.setDescription(cursor.getString(cursor.getColumnIndex(IWeatherDao.COLUMN_DESCRIPTION)));
            entry.setMax(cursor.getInt(cursor.getColumnIndex(IWeatherDao.COLUMN_MAX_TEMP)));
            entry.setMin(cursor.getInt(cursor.getColumnIndex(IWeatherDao.COLUMN_MIN_TEMP)));
            entry.setIconId(cursor.getInt(cursor.getColumnIndex(IWeatherDao.COLUMN_WEATHER_ICON_ID)));
            entry.setHumidity(cursor.getString(cursor.getColumnIndex(IWeatherDao.COLUMN_HUMIDITY)));
            entry.setWind(cursor.getFloat(cursor.getColumnIndex(IWeatherDao.COLUMN_WIND_SPEED)));
            entry.setWindDirection(cursor.getFloat(cursor.getColumnIndex(IWeatherDao.COLUMN_DEGREES)));

            result.add(entry);
        }
        return result;
    }
}
